'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');
var glob = require('glob');
var chalk = require('chalk');
var _ = require('underscore');
_.mixin(require('underscore.inflections'));
var angularUtils = require('./utils.js');
var preference = require('./preference');
var fs = require('fs');
var q = require('q');
/**
 * Constructor
 */
var Generator = module.exports = function() {

    yeoman.generators.NamedBase.apply(this, arguments);

    var bowerJson = {};

    try {
        bowerJson = require(path.join(process.cwd(), 'bower.json'));
    } catch (e) {
        // nothing to do here
    }

    if (bowerJson.name) {
        this.appname = bowerJson.name;
    } else {
        this.appname = path.basename(process.cwd());
    }

    if (!this.env.options.appPath && bowerJson.appPath) {
        this.env.options.appPath = bowerJson.appPath;
    }

    this.appname = _.slugify(_.humanize(this.appname));
    this.scriptAppName = bowerJson.moduleName || _.camelize(this.appname) + angularUtils.appName(this);
    this.cameledName = _.camelize(this.name);
    this.classedName = _.classify(this.name);
    // get back the settings
    this.settings = this.getPanesConfig();

    this.option('cn' , {
        type: String,
        desc: 'Change to Chinese'
    });

    this.lang = (this.settings) ? this.settings.lang : (this.options.cn ? 'cn' : 'en');

    var interactive = {
        type: String,
        desc: (this.lang==='cn') ? '交互方式' : 'Interactive mode'
    };

    this.option('interactive' , interactive);
    this.option('ia' , interactive);
    this.interactive = this.options.interactive || this.options.ia;
};

util.inherits(Generator, yeoman.generators.NamedBase);

/**
 * add a template file
 */
Generator.prototype.appTemplate = function(src, dest , destScriptSuffic)
{
    var endScriptSuffix = destScriptSuffic || this.scriptSuffix;
    yeoman.generators.Base.prototype.template.apply(this, [
        src + this.scriptSuffix,
        path.join(this.env.options.appPath, dest.toLowerCase()) + endScriptSuffix
    ]);
};

/**
 * test the template file
 */
Generator.prototype.testTemplate = function(src, dest)
{
    if (!this.env.options.testPath) {
        this.env.options.testPath = path.join(this.env.options.appPath , 'client' , 'web' , 'test');
    }
    // @TODO need to fix this later about the test path
    yeoman.generators.Base.prototype.template.apply(this, [
        src + this.scriptSuffix,
        path.join(this.env.options.testPath, dest.toLowerCase()) + this.scriptSuffix
    ]);
};

/**
 * generate html template
 */
Generator.prototype.htmlTemplate = function(src, dest)
{
    yeoman.generators.Base.prototype.template.apply(this, [
        src,
        path.join(this.env.options.appPath, dest.toLowerCase())
    ]);
};

/**
 * this is for the client side to get the source root directory
 */
Generator.prototype.getClientSourceRoot = function()
{
    var sourceRootBase = path.join(__dirname , '..' , 'generators' , 'templates' , 'common' , 'app' , 'client');
    var sourceRoot = path.join(sourceRootBase , 'javascript');
    this.scriptSuffix = '.js';

    if (this.settings) {
        if (this.settings.client['scriptingLang']) {
            this.env.options.coffee = (this.settings.client['scriptingLang']==='CS');
            this.env.options.typescript = (this.settings.client['scriptingLang']==='TS');
        }
    }

    if (this.env.options.coffee) {
        sourceRoot = path.join( sourceRootBase , 'coffeescript');
        this.scriptSuffix = '.coffee';
    }

    if (this.env.options.typescript) {
        sourceRoot = path.join(sourceRootBase , 'typescript');
        this.scriptSuffix = '.ts';
    }

    this.sourceRoot(sourceRoot);
};

/**
 * this is getting re-use everywhere
 * 22.09.2015 add appPath parameter for use with client side sub generator
 */
Generator.prototype.generateSourceAndTest = function(appTemplate, testTemplate, targetDirectory , appPath)
{
    appPath = appPath || 'server';
    this.appTemplate(appTemplate, path.join(appPath , targetDirectory, this.name));
    this.testTemplate(testTemplate, path.join(targetDirectory, this.name));
};

/**
 * insert a route into the route template
 */
Generator.prototype.getRouteEntry = function(routes)
{
    // we need to have this fix point. because the app path keep changing!
    // @TODO use preference to find out the exact app path?
    var _path = path.resolve(process.cwd() , 'app' , 'config' , 'routes.js');
    var routes = require(_path);
    return routes;
};

/**
 * recreate a new route file
 */
Generator.prototype.generateNewRoute = function(newRoutes)
{
    var _this = this;
    var routes = _this.getRouteEntry();
    var allRoutes = (routes && _.isObject(routes)) ?  _.extend(routes , newRoutes) : allRoutes;
    var fileName = 'routes.js';
    var dest = path.join(_this.env.options.appPath, 'config' , fileName);
    // setup source root
    _this.sourceRoot(path.join(__dirname, path.join( '..' , 'generators' , 'templates','common','app','config')));
    // need to remove the original file
    fs.unlink(dest , function() {
        // then replace it with a new generated route template
        _this.routesDefinition = JSON.stringify(allRoutes , null , 4);
        yeoman.generators.Base.prototype.template.apply(_this, [
            fileName,
            dest
        ]);
    });
};
/**
 * getting back the panesjs config file
 */
Generator.prototype.getPanesConfig = function(key)
{
    return preference.getConfig(key);
};


/**
 * ask if they want to exit and write to file
 * this was original develop inside the model/ but this could be useful to all
 */
Generator.prototype._askIfWantToExit = function(message)
{
    message = message || {cn: chalk.yellow('完成?') , en: chalk.yellow('Finish?')};
    var _this = this;
    var cb = _this.async();
    var defer = q.defer();
    _this.prompt({
        type: 'confirm',
        name: 'exit',
        message: message[_this.lang],
        default: false
    } , function(props)
    {
        cb();
        defer.resolve(props.exit);
    }.bind(this));
    // need to return it
    return defer.promise;
};
